/**
 * @particulars 重写数组的七个变异方法
 */

// 1、获取拷贝一份数组原型，并创建一个以数组原原型为原型的对象
const oldArrayProto = Array.prototype;
const newArrayProto = Object.create(oldArrayProto);
const methods = ['push', 'pop', 'shift', 'unshift', 'sort', 'splice'];

// 2、重写数组方法
methods.forEach(method => {
  // 为新建的原型挂载对应的变异方法
  newArrayProto[method] = function (...args) {
    // 内部调用的还是数组原来的方法
    const result = oldArrayProto[method].call(this, ...args);

    // 数组新增的内容，也需要重新被劫持（push、unshift、splice）
    let inserted;
    // 数据上所挂载的__ob__ 属性是Observer 的实例，上面挂载有劫持属性的方法
    const ob = this.__ob__;

    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args;
        break;
      case 'splice':
        // splice(startIndex, endIndex, addData......) => splice 的第三个参数之后就是新增的内容
        inserted = args.slice(2);
        break;
      default:
        break;
    };

    // ob.observerArray 劫持数组元素的方法，对数组新增的元素进行劫持
    if (inserted) ob.observerArray(inserted);

    // 调用了数组的变异方法，数组发生变化通知更新
    ob.dep.notify();

    // 返回变异方法执行的结果
    return result;
  }
})

// 导出新创建的数组原型，这样通过劫持后的数组访问到的变异方法就是新原型上的
export default newArrayProto

